<?php

namespace tools;

class Redis
{
    private $redis;        //redis类
    private $expire = 600;    //默认过期时长，秒
    private $host = '127.0.0.1';
    private $port = 6379;

    /**
     *    Redis配置
     * $select      连接选择的数据库
     *      1   token
     *      2   webconfig
     */
    public function __construct($select=1,$host = '', $port = 0)
    {

        $this->redis = new \Redis();

        if ($host != '' && $port != 0) {
            $this->redis->connect($host, $port);
        } else {
            $this->redis->connect($this->host, $this->port);
        }
        $this->redis->auth('123456');
        $this->redis->select($select);
        if($select ==1 ){
            $this->expire=0;
        }
    }

    /**
     *    为指定的 key 设置值及其过期时间。如果 key 已经存在， SETEX 命令将会替换旧的值
     */
    public function setex($key, $time, $val)
    {
        return $this->redis->setex($key, $time, $val);
    }

    /**
     *    设置 key 和过期时间
     */
    public function set($key, $val,$time = '')
    {
        $time = $time == '' ? $this->expire : $time;
        $keys = explode('.', $key);
        $data = $this->get($keys[0]);
        if (count($keys)==1){
            $data = $val;
        }elseif (count($keys)==2){
            $data[$keys[1]] = $val;
        }elseif (count($keys)==3){
            $data[$keys[1]][$keys[2]] = $val;
        }elseif (count($keys)==4){
            $data[$keys[1]][$keys[2]][$keys[3]] = $val;
        }
        $val = is_array($data) ? json_encode($data) : $data;
        if ($time == 0) {
            return $this->redis->set($keys[0], $val);
        } else {
            return $this->setex($keys[0], $time, $val);
        }
    }

    /**
     *    获取key的值
     * $default     默认值
     */
    public function get($key, $default = null)
    {
        $keys = explode('.', $key);
        if (count($keys)>1){
            $res = json_decode($this->redis->get($keys[0]), true);
            if (!$res){
                return $default;
            }
            unset($keys[0]);
            return $this->getkey($res, $keys, $default);
        }else{
            return $this->redis->get($keys[0]);
        }
    }

    /**
     *    获取key的值并更新过期时间
     * $default     默认值
     */
    public function getAndExpire($key, $time='',$default = null)
    {
        $keys = explode('.', $key);
        $time = $time == '' ? $this->expire : $time;
        $this->expire($keys[0],$time);
        return $this->get($key,$default);
    }

    /**
     * 获取指定多维key
     */
    protected function getkey($res, $keys, $default, $index = 0)
    {
        if ($keys) {
            $k = $index + 1;
            if (!array_key_exists($keys[$k], $res)) {
                return $default;
            }
            $a = $res[$keys[$k]];
            unset($keys[$k]);
            return $this->getkey($a, $keys, $default, $k);
        }
        return $res;
    }

    /**
     *    为key设置过期时间
     */
    public function expire($key, $time = '')
    {
        $time = $time == '' ? $this->expire : $time;
        return $this->redis->expire($key, $time);
    }

    /**
     *    判断key是否存在
     */
    public function has($key)
    {
        return $this->redis->exists($key);
    }

    /**
     *    删除key
     */
    public function delete($key)
    {
        return $this->redis->delete($key);
    }

    /**
     *    过期事件绑定
     */
    public function psubscribe($patterns = array(), $callback)
    {
        $this->redis->psubscribe($patterns, $callback);
    }

    /**
     * 清空数据库
     */
    public function flushAll(){
        $this->redis->flushAll();
    }



    /***************************列表*******************************/

    /**
     *    由列表头部添加字符串值
     *  成功返回数组长度，失败false
     *  如果不存在该键则创建该列表。如果该键存在，而且不是一个列表，返回FALSE
     */
    public function lpush($key, $value)
    {
        $this->redis->lpush($key, $value);
    }

    /**
     *    由列表尾部添加字符串值
     *  成功返回数组长度，失败false
     *  如果不存在该键则创建该列表。如果该键存在，而且不是一个列表，返回FALSE。
     */
    public function rpush($key, $value)
    {
        $this->redis->rpush($key, $value);
    }

    /**
     * 返回和移除列表的第一个元素
     * 成功返回第一个元素的值 ，失败返回false
     */
    public function lpop($key)
    {
        $this->redis->lpop($key);
    }

    /**
     * 返回的列表的长度。如果列表不存在或为空，该命令返回0。如果该键不是列表，该命令返回FALSE。
     * 成功返回数组长度，失败false
     */
    public function lsize($key)
    {
        $this->redis->lsize($key);
    }

    /**
     * 为一个Key添加一个值。如果这个值已经在这个Key中，则返回FALSE。
     * 成功返回true,失败false
     */
    public function sadd($key, $value)
    {
        $this->redis->sadd($key, $value);
    }

    /**
     * 删除Key中指定的value值
     * true or falsee
     */
    public function sremove($key)
    {
        $this->redis->sremove($key);
    }

    /**
     *    解决Redis客户端订阅时候超时情况
     */
    public function setOption()
    {
        $this->redis->setOption(\Redis::OPT_READ_TIMEOUT, -1);
    }

}